// 数据包后面添加标记符号，然后在前面添加长度
package wirepack

import (
	"fmt"
)

const SBMLLPEBCR = "mllp"

// 分隔符
var MLLPSB = []byte("\x0B")
var MLLPEBCR = []byte("\x1C\x0D")

var MLLP_SB = byte(0x0b)
var MLLP_EB = byte(0x1c)
var MLLP_CR = byte(0x0d)

const MLLPMAXLEN = (100 * 1024)

type MllpDecodeState int

const (
	DECODE_START MllpDecodeState = iota
	DECODE_FOUND_SB
	DECODE_FOUND_EB
	// DECODE_FOUND_EB_CR
)

// SB + HL7 + EB + CR
type SbMllpEbCr struct {
	buf  []byte
	stat MllpDecodeState
}

func NewSbMllpEbCrPkt() *SbMllpEbCr {
	return &SbMllpEbCr{
		buf: make([]byte, 0),
	}
}

func (p *SbMllpEbCr) Protocol() string {
	return SBMLLPEBCR
}

func (p *SbMllpEbCr) Pack(buf []byte) []byte {
	return ByteSliceCombine(MLLPSB, buf, MLLPEBCR)
}

// 解码MLLP数据包
func (p *SbMllpEbCr) Decode(dat []byte) [][]byte {
	mllps := make([][]byte, 0)

	for _, b := range dat {
		switch p.stat {
		case DECODE_START:
			if b != MLLP_SB {
				// fmt.Println("not SB")
				continue
			}
			p.buf = append(p.buf, b)
			p.stat = DECODE_FOUND_SB
		case DECODE_FOUND_SB:
			p.buf = append(p.buf, b)
			if b == MLLP_EB {
				p.stat = DECODE_FOUND_EB
			}
			if len(p.buf) > MLLPMAXLEN {
				// 超过最大包仍未解码成功，重新解码
				fmt.Println("drop data")
				p.buf = make([]byte, 0)
				p.stat = DECODE_START
			}
		case DECODE_FOUND_EB:
			if b == MLLP_CR {
				// 解包成功, p.buf为完整包数据
				p.buf = append(p.buf, b)
				mllps = append(mllps, p.buf)
			}
			// 解包成功或失败
			// 重建缓冲区，旧的缓冲区为待返回的解包数据
			// p.buf = p.buf[0:0] // 不能用这种方法
			p.buf = make([]byte, 0)
			p.stat = DECODE_START
			if b == MLLP_SB {
				// SB字符不丢弃
				p.buf = append(p.buf, b)
			}
		}
	}

	return mllps
}
